package wowraidmanager.client.auction.data.canvas;

import java.util.ArrayList;

import wowraidmanager.client.auction.data.calculate.CalculateData;
import wowraidmanager.shared.model.auction.AuctionList;
import wowraidmanager.shared.model.auction.canvas.AuctionDistributionData;
import wowraidmanager.shared.model.auction.canvas.TooltipData;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.Context2d.TextAlign;
import com.google.gwt.canvas.dom.client.Context2d.TextBaseline;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;

public class DrawDistributionCanvas extends BaseDrawCanvas{

    static String REGION_ALLIANCE = "alliance";
    static String REGION_HORDE = "horde";
    static String REGION_NEUTRAL = "neutral";

    Canvas tooltipCanvas;
    Context2d tooltipContext;

    CalculateData calculateData = new CalculateData();

    ArrayList<AuctionDistributionData> auctionDistributionDataList;

    long max_quantity;
    long min_quantity = 0;

    int graphWidth = 300;
    int graphHeight = 200;

    int graphBeginX = 50;
    int graphBeginY = 50;

    int maximumGraphWidth = 20;

    int column_width;
    int column_quantity;

    String regionType;

    public DrawDistributionCanvas(Canvas dataCanvas, Canvas tooltipCanvas){
        super(dataCanvas);
        this.tooltipCanvas = tooltipCanvas;
        tooltipContext = tooltipCanvas.getContext2d();
    }

    public void setAuctionData(ArrayList<AuctionList> auctionListList, String regionType){
        for(AuctionList auctionList:auctionListList){
            auctionDistributionDataList = calculateData.calcAuctionDistributionData(auctionList);
        }

        this.regionType = regionType;

        if(auctionListList.size() == 0){
            setClear();
        }else{
            setInit();
            checkQuantiry();
            drawBaseGraph();
            setTooltip();
            drawDistributionGraph();
        }
    }

    private void setTooltip(){
        tooltipDataList = new ArrayList<TooltipData>();
        tooltipCanvas.addMouseMoveHandler(new MouseMoveHandler(){

            public void onMouseMove(MouseMoveEvent event){
                checkTooltipPosition(event.getX(), event.getY());
            }
        });

    }

    protected void checkTooltipPosition(int x, int y){
        boolean isContain = false;
        for(TooltipData tooltipData:tooltipDataList){
            if(tooltipData.getPositionStartX() < x && tooltipData.getPositionStartY() < y && tooltipData.getPositionEndX() > x && tooltipData.getPositionEndY() > y){
                drawTooltip(x, y, tooltipData.getMessage());
                isContain = true;
                break;
            }
        }
        if(isContain == false){
            tooltipContext.clearRect(0, 0, 400, 300);
        }
    }

    private void drawTooltip(int x, int y, String message){
        String[] messageList = message.split("_");
        int messageLine = messageList.length;
        tooltipContext.clearRect(0, 0, 400, 300);
        double stringWidth = Double.MIN_VALUE;
        for(String widthMessage:messageList){
            double width = tooltipContext.measureText(widthMessage).getWidth();
            if(stringWidth < width){
                stringWidth = width;
            }
        }

        boolean isOverWidth = false;

        if(stringWidth + x + 20 > 400){
            isOverWidth = true;
        }

        tooltipContext.setFont("10px 'Helvetica'");
        tooltipContext.beginPath();
        tooltipContext.setLineWidth(1);
        tooltipContext.setStrokeStyle("black");
        tooltipContext.setFillStyle("white");
        if(isOverWidth){
            tooltipContext.rect(x - stringWidth, y -20, stringWidth + 15, 20 * messageLine);
            tooltipContext.setTextAlign(TextAlign.RIGHT);
        }else{
            tooltipContext.rect(x + 15, y - 20, stringWidth + 15, 20 * messageLine);
            tooltipContext.setTextAlign(TextAlign.LEFT);
        }
        tooltipContext.fill();
        tooltipContext.stroke();

        tooltipContext.setTextBaseline(TextBaseline.TOP);
        tooltipContext.setFillStyle("black");
        int countLine = 0;
        if(isOverWidth){
            for(String messageString:messageList){
                tooltipContext.fillText(messageString, x + 15, (y - 15) + (countLine * 15));
                countLine++;
            }
        }else{
            for(String messageString:messageList){
                tooltipContext.fillText(messageString, x + 20, (y - 15) + (countLine * 15));
            countLine++;
            }
        }
    }

    private void drawDistributionGraph(){
        int start_graphWidth = (graphWidth - (column_quantity * column_width)) / 2 + graphBeginX;
        int column = 0;
        dataContext.beginPath();
        if(regionType.endsWith(REGION_ALLIANCE)){
            dataContext.setFillStyle(allianceAverageColor);
        }else if(regionType.equals(REGION_HORDE)){
            dataContext.setFillStyle(hordeAverageColor);
        }else if(regionType.equals(REGION_NEUTRAL)){
            dataContext.setFillStyle(neutralAverageColor);
        }
        dataContext.setStrokeStyle(textColor);
        tooltipContext.setLineWidth(1);
        for(AuctionDistributionData auctionDistributionData:auctionDistributionDataList){
            long lineY = getLineY(auctionDistributionData.getTotalQuantity());
            long startX = start_graphWidth + (column * column_width);
            long startY = graphBeginY + (graphHeight - lineY);
            dataContext.strokeRect(startX, startY, column_width, lineY);
            addTooltipData((int)startX, (int)startY, (int)(startX + column_width), (int)(startY + lineY), calculateData.toGold(auctionDistributionData.getBuyoutPrice()) + "_" + auctionDistributionData.getTotalQuantity());
            column++;
        }
    }

    private void addTooltipData(int beginX, int beginY, int endX, int endY, String message){
        TooltipData tooltipData = new TooltipData();
        tooltipData.setPositionStartX(beginX);
        tooltipData.setPositionStartY(beginY);
        tooltipData.setPositionEndX(endX);
        tooltipData.setPositionEndY(endY);
        tooltipData.setMessage(message);
        tooltipDataList.add(tooltipData);
    }

    private long getLineY(long targetQuantity){
        if(max_quantity == min_quantity){
            return 0;
        }else{
            return (targetQuantity - min_quantity) * 200 / (max_quantity - min_quantity);
        }
    }
    private void checkQuantiry(){
        column_quantity = 0;
        for(AuctionDistributionData auctionDistributionData:auctionDistributionDataList){
            long currentQuantity = auctionDistributionData.getTotalQuantity();
            if(currentQuantity > max_quantity){
                max_quantity = currentQuantity;
            }
            column_quantity ++;
        }

        column_width = graphWidth / column_quantity;

        if(column_width > maximumGraphWidth){
            column_width = maximumGraphWidth;
        }
    }

    private void drawBaseGraph(){
        dataContext.setFillStyle(backGroundColor);
        dataContext.beginPath();
        dataContext.fillRect(0, 0, 400, 300);
        dataContext.setStrokeStyle(textColor);
        dataContext.setLineWidth(1);
        dataContext.moveTo(50, 50);
        dataContext.lineTo(50, 250);
        dataContext.lineTo(350, 250);
        dataContext.stroke();

        dataContext.setFillStyle(textColor);
        dataContext.setFont("10px 'Helvetica'");

        dataContext.setTextAlign(TextAlign.RIGHT);
        dataContext.setTextBaseline(TextBaseline.MIDDLE);
        if(max_quantity != Long.MIN_VALUE){
            dataContext.fillText(String.valueOf(max_quantity), 45, 50);
            dataContext.fillText(String.valueOf((max_quantity + min_quantity) / 2), 45, 150);
            dataContext.fillText(String.valueOf(min_quantity), 45, 250);
        }

        dataContext.setTextAlign(TextAlign.LEFT);
        if(regionType.equals(REGION_ALLIANCE)){
            dataContext.setFillStyle(allianceMinimumColor);
            dataContext.fillText("Alliance", 10, 10);
        }else if(regionType.equals(REGION_HORDE)){
            dataContext.setFillStyle(hordeMinimumColor);
            dataContext.fillText("Horde", 10, 10);

        }else if(regionType.equals(REGION_NEUTRAL)){
            dataContext.setFillStyle(neutralMinimumColor);
            dataContext.fillText("Neutral", 10, 10);

        }
    }

    private void setInit(){
        max_quantity = Long.MIN_VALUE;
    }

}
